package arcane.jibx.io;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.DataFormatException;

import org.jibx.runtime.BindingDirectory;
import org.jibx.runtime.IBindingFactory;
import org.jibx.runtime.IMarshallingContext;
import org.jibx.runtime.IUnmarshallingContext;
import org.jibx.runtime.JiBXException;
import org.jibx.runtime.impl.UnmarshallingContext;

import ps.object.particle.ParticleGenerator;
import ps.object.particle.ParticleSystem;
import ps.object.particle.ParticleSystemManager;
import ps.object.particle.ParticleUpdater;

public class JibxIO {
	IBindingFactory factory;

	public JibxIO() {
	}

	public JibxIO(Class aClass) {
		try {
			factory = BindingDirectory.getFactory(aClass);
		} catch (JiBXException e) {
			e.printStackTrace();
		}
	}

	public Object load(String fileName, Class c) throws IOException,
			DataFormatException, JiBXException {
		File file = new File(fileName);
		InputStream fis = new FileInputStream(file);
		IBindingFactory bfact = BindingDirectory.getFactory(c);
		IUnmarshallingContext umctx = bfact.createUnmarshallingContext();
		Object obj = umctx.unmarshalDocument(fis, fileName, null);
		fis.close();
		return obj;
	}

	public Object load(String fileName, Object obj) throws IOException,
			DataFormatException, JiBXException {
		return load(fileName, obj.getClass());
	}

	public ParticleSystem loadSystem(String filename) throws IOException,
			DataFormatException, JiBXException {
		InputStream fis = new FileInputStream(filename);
		try {
			UnmarshallingContext umctx = (UnmarshallingContext) factory
					.createUnmarshallingContext();
			ParticleSystem system = (ParticleSystem) umctx.unmarshalElement();
			fis.close();
			return system;
		} catch (Exception e) {
			System.out.println("Exception " + e + " occured!");
			e.printStackTrace();
			return null;
		}
	}

	public ParticleSystemManager loadManager(String filename)
			throws IOException, DataFormatException, JiBXException {
		InputStream fis = new FileInputStream(filename);

		factory = BindingDirectory.getFactory(ParticleSystemManager.class);

		IUnmarshallingContext umctx = factory.createUnmarshallingContext();
		ParticleSystemManager manager = (ParticleSystemManager) umctx
				.unmarshalDocument(fis, null);
		fis.close();
		return manager;
	}

	public void save(File file, Object obj) throws IOException,
			DataFormatException, JiBXException {
		FileOutputStream fos = new FileOutputStream(file);
		BufferedOutputStream bos = new BufferedOutputStream(fos, 2048);

		String filename = file.getName().substring(0,
				file.getName().indexOf('.'));
		System.out.println("Saving " + file.getName() + " as an xml file : "
				+ filename + ".xml");

		IMarshallingContext mctx;
		mctx = factory.createMarshallingContext();
		mctx.setIndent(4);
		mctx.marshalDocument(obj, "UTF-8", null, bos);
		bos.close();
	}

	public static void main(String[] arg) {
		JibxIO io = new JibxIO(ParticleSystemManager.class);
		try {
			ParticleSystemManager manager = new ParticleSystemManager(
					"Some manager");
			for (int i = 0; i < 1; i++) {
				manager.addSystem(new ParticleSystem("System " + i));
				manager.addSystem(new ParticleSystem("This is system " + i
						+ "2"));
				manager.addGenerator(new ParticleGenerator("Generator " + i));
				manager.addUpdater(new ParticleUpdater("Updater " + i));
			}

			io.save(new File("bleh.xml"), manager);
			try {
				System.out.println("Load bleh.xml into memory");
				Object obj = io.load("bleh.xml", ParticleSystemManager.class);
				manager = (ParticleSystemManager) obj;
				System.out.println(obj.getClass() + " " + obj.toString()
						+ " <---- reloaded object");
			} catch (Exception e) {
				System.err.println("Error loading bleh.xml");
				e.printStackTrace();
			}

			System.out.println(manager);

			for (int i = 0; i < manager.getGenerators().size(); i++)
				System.out.println(manager.getGenerator(i));

			for (int i = 0; i < manager.getUpdaters().size(); i++)
				System.out.println(manager.getUpdater(i));

			for (int i = 0; i < manager.getSystems().size(); i++)
				System.out.println(manager.getSystem(i));
		} catch (Exception e) {
			System.out.println("Exception caught in main.");
			e.printStackTrace();
		}
	}
}
